package org.geektimes.configuration.microprofile.config.source.servlet;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.spi.ConfigBuilder;
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
import org.geektimes.context.ClassicComponentContext;
import org.geektimes.context.ComponentContext;
import org.geektimes.projects.user.domain.User;
import org.geektimes.projects.user.management.UserManager;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.lang.management.ManagementFactory;


/**
 * 如何注册当前 ServletContextListener 实现
 *
 * @see ServletConfigInitializer
 */
public class ServletContextConfigInitializer implements ServletContextListener {


    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext servletContext = servletContextEvent.getServletContext();
        ServletContextConfigSource servletContextConfigSource = ServletContextConfigSource.getInstance(servletContext);
        // 加载Config配置
        loadConfig(servletContext, servletContextConfigSource);
        // 组件初始化
        initComponent(servletContext);
        // 注册MBean
        registerMBean();
    }

    /**
     * 组件初始化
     * @param servletContext servletContext
     */
    private void initComponent(ServletContext servletContext) {
        ClassicComponentContext classicComponentContext = new ClassicComponentContext();
        classicComponentContext.init(servletContext);
    }

    /**
     * 加载Config配置
     * @param servletContext servletContext
     * @param servletContextConfigSource servletContextConfigSource
     */
    private void loadConfig(ServletContext servletContext, ServletContextConfigSource servletContextConfigSource) {
        // 获取当前 ClassLoader
        ClassLoader classLoader = servletContext.getClassLoader();
        ConfigProviderResolver configProviderResolver = ConfigProviderResolver.instance();
        ConfigBuilder configBuilder = configProviderResolver.getBuilder();
        // 配置 ClassLoader
        configBuilder.forClassLoader(classLoader);
        // 默认配置源（内建的，静态的）
        configBuilder.addDefaultSources();
        // 通过发现配置源（动态的）
        configBuilder.addDiscoveredConverters();
        // 增加扩展配置源（基于 Servlet 引擎）
        configBuilder.withSources(servletContextConfigSource);
        // 获取 Config
        Config config = configBuilder.build();
        // 注册 Config 关联到当前 ClassLoader
        configProviderResolver.registerConfig(config, classLoader);
        // Config 放入ServletContext中
        servletContext.setAttribute("WEBAPP_SERVLET_CONFIG", config);
    }

    /**
     * 注册MBean
     */
    private void registerMBean () {
        try {
            // 获取平台 MBean Server
            MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
            // 为 UserMXBean 定义 ObjectName
            ObjectName objectName = new ObjectName("jolokia:name=User");
            // 创建 UserMBean 实例
            User user = new User();
            mBeanServer.registerMBean(new UserManager(user), objectName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
//        ServletContext servletContext = servletContextEvent.getServletContext();
//        ClassLoader classLoader = servletContext.getClassLoader();
//        ConfigProviderResolver configProviderResolver = ConfigProviderResolver.instance();
//        Config config = configProviderResolver.getConfig(classLoader);
        ComponentContext context = ClassicComponentContext.getInstance();
        context.destroy();
    }
}
